/**
 * ComputerPlayer is a GhostGame player that implements an optimal
 * strategy.
 * <br>
 * This source code is copyright 2008 by Patrick May.  All rights
 * reserved.
 *
 * @author Patrick May (patrick.may@mac.com)
 * @author &copy; 2008 Patrick May.  All rights reserved.
 * @version 1
 */

package com.game.ghost.webapp.apps.player;

import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.game.ghost.webapp.apps.data.WordNode;
import com.game.ghost.webapp.apps.service.GhostWordsService;

/**
 * This class allows system player to perform logic to get word random word selection 
 * 
 * @author gautak
 *
 */
@Component("systemPlayer")
public class SystemPlayer implements GamePlayer
{

  private static Logger logger = Logger.getLogger(SystemPlayer.class.getName());

  @Value("${system.player.name}")
  private String name_;
  
  @Autowired
  private GhostWordsService ghostWordsService;
  

  /**
   * The default constructor for the ComputerPlayer class.
   */
  public SystemPlayer()
    {
    }


  /**
   * The name of the player.  This method is inherited from GhostPlayer.
   */
  public String name() { return name_; }

  /**
   * Compute the forced wins possible in the tree rooted at the
   * specified node.  A forced win occurs from a particular node when
   * either a child node is a terminal or all of the grandchild nodes
   * for a particular child node contain a forced win.
   *
   * @param wordNode The node representing the root of the tree to search.
   */
  private void findForcedWins(WordNode wordNode)
    {
    boolean forcedWin = false;
    Collection<WordNode> childNodes = wordNode.childNodes();
    Iterator<WordNode> children = childNodes.iterator();
    WordNode child = null;

    while (children.hasNext())
      {
      child = children.next();

      boolean childForcedWin = true;
      if (!child.isTerminalNode())
        {
        WordNode grandchild = null;
        Iterator<WordNode> grandchildren = child.childNodes().iterator();

        while (grandchildren.hasNext())
          {
          grandchild = grandchildren.next();

          if (grandchild.isTerminalNode())
            grandchild.flagForcedWin(false);
          else
            findForcedWins(grandchild);

          if (!grandchild.isForcedWin())
            childForcedWin = false;
          }
        }
      child.flagForcedWin(childForcedWin);

      if (child.isForcedWin())
        forcedWin = true;
      }

    wordNode.flagForcedWin(forcedWin);
    }


  /**
   * Choose the next word to play.
   *
   * @param wordNode The node representing the root of the tree to search.
   * @return A guaranteed winning word or the longest losing word if no
   *         forced win exists.
   */
  private String chooseWord(WordNode wordNode)
    {
    if (wordNode.isForcedWin() == null)
      findForcedWins(wordNode);

    return wordNode.isForcedWin() ? wordNode.firstWinningWord()
                                  : wordNode.longestLosingWord();
    }


  /**
   * Get the player's next letter.  This method is inherited from
   * GhostPlayer.
   *
   * @param wordInPlay The word currently being played.
   */
  public Character play(String wordInPlay)
    {
    WordNode wordNode = ghostWordsService.getWordNode(wordInPlay);

    if ((wordNode == null) || (wordNode.numberOfChildren() == 0))
      return null;

    return chooseWord(wordNode).charAt(wordInPlay.length());
    }
}  
